package com.southsmart.sgeocserver.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.southsmart.sgeocserver.api.RedisService;
import com.southsmart.sgeocserver.config.JdbcDatasource;
import com.southsmart.sgeocserver.exception.Asserts;
import com.southsmart.sgeocserver.service.ILayerService;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author cjunxian
 * @description 图层服务接口实现类
 * @date  2021/07/29
 */
@Service(value = ILayerService.BEAN_NAME)
public class LayerServiceImpl implements ILayerService{

    @Resource(name = JdbcDatasource.BEAN_NAME)
    JdbcDatasource jdbcDatasource;

    @Resource(name = RedisService.BEAN_NAME)
    RedisService redisService;

    /**
     * tile在redis中的Key前缀
     */
    public final static String TILEKEY = "tile:";

    @Override
    public String getLayerJson(String key) {

        if(StrUtil.isEmpty(key)){
            Asserts.fail("数据库key值不能为空！");
        }

        DruidDataSource datasource = jdbcDatasource.getDatasource(key);
        String sql = "select layerjson from infos";
        return new JdbcTemplate(datasource).queryForObject(sql, String.class);

    }

    @Override
    public Byte[] getTile(String key, int z, double x, double y) {
        //设置不同的过期时间防止缓存雪崩
        long expireTime = (long) (60 + (1 + Math.random() * 59));
        String redisKey = buildRedisKey(key,z,x,y);

        if(redisService.hasKey(redisKey)){
            JSONArray jsonArray = JSONArray.parseArray((String) redisService.get(redisKey));
            if(jsonArray == null) {
                return null;
            }
            Byte[] tile = new Byte[jsonArray.size()];
            for (int i = 0; i < jsonArray.size(); i++) {
                tile[i] = jsonArray.getByte(i);
            }
            return tile;
        }

        DruidDataSource datasource = jdbcDatasource.getDatasource(key);
        JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource);
        String table = "blocks";
        int a = (int)(x/512);
        int b = (int)(y/512);
        StringBuilder sql = new StringBuilder("select tile from ");
        if(z > 9) {
            table = table + "_"+z+"_"+a+"_"+b;
        }
        sql.append(table);
        sql.append(" where z=").append(z).append(" and x=").append(x).append(" and y=").append(y);

        Byte[] tiles = null;
        try {
            tiles = jdbcTemplate.queryForObject(sql.toString(), Byte[].class);
            String tilestr = JSONObject.toJSONString(tiles);
            redisService.set(redisKey,tilestr,expireTime);
        }catch (EmptyResultDataAccessException| UncategorizedSQLException e){
            //null一律缓存，防止缓存穿透。
            redisService.set(redisKey,null,expireTime);
        }catch (Exception e){
            Asserts.fail("查询数据库失败！");
        }
        return tiles;
    }

    String buildRedisKey(String key, int z ,double x,double y){
        return TILEKEY + key + "_" + z + "_" + x + "_" + y;
    }

}
